4.4 🔥 Виджеты. Checkbox FAB AlertDialog Switch
3 из 3 шагов пройдено

 Виджеты. Checkbox FAB AlertDialog Switch

➡️Ссылка на репозиторий с кодом этого урока

Виджет Switch

Виджет Switch - это переключатель между двумя значениями (вкл/выкл). Он часто используется для настроек.

Switch(    
  value: widget.isDarkMode,  
  onChanged: widget.onThemeToggle,  
),

Основные свойства Switch:

  • valuebool - текущее состояние переключателя (true - включен, false - выключен).
  • onChanged: - колбэк-функция, вызываемая при изменении состояния переключателя пользователем. Эта функция принимает новое состояние (true или false). Как и для Checkbox, внутри onChanged мы обычно вызываем setState() для обновления UI.

Для смены темы нам нужно управлять свойством themeMode виджета MaterialApp. Поскольку MaterialApp находится выше в дереве виджетов, чем наш TaskListScreen, нам потребуется поднять состояние темы выше или использовать простой механизм передачи данных вниз и колбэков вверх. Для этого примера мы сделаем MyApp StatefulWidget и будем передавать текущую тему и функцию переключения в TaskListScreen.

 

Смена цветовой темы приложения через Switch

Изменим MyApp, чтобы он стал StatefulWidget и управлял темой, а затем передадим эту логику в TaskListScreen через конструктор.

Файл main.dart

void main() {  
  runApp(const ToDoApp());  
}  
  
class ToDoApp extends StatefulWidget {  
  const ToDoApp({super.key});  
  @override  
  State<ToDoApp> createState() => _ToDoAppState();  
}  
  
class _ToDoAppState extends State<ToDoApp> {  
  
  // Состояние темы: true - тёмная, false - светлая  
  bool _isDarkMode = false;  
  
  // Метод для переключения темы  
  void _toggleTheme(bool newValue) {  
    setState(() {  
      _isDarkMode = newValue;  
    });  
  }  
  
  @override  
  Widget build(BuildContext context) {  
    return MaterialApp(  
      title: "Список Дел",  
      theme: ThemeData(  
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue), // Цвета  
      ),  
      darkTheme: ThemeData.dark(),  
      themeMode: _isDarkMode ? ThemeMode.dark : ThemeMode.light, // Текущая тема  
      debugShowCheckedModeBanner: false,  
  
      // Передаем состояние темы и функцию переключения в TaskListScreen  
      home: ToDoScreen(  
        isDarkMode: _isDarkMode,  
        onThemeToggle: _toggleTheme,  
      ),  
  
    );  
  }  
}

Добавим виджет Switch в AppBar  Scaffold → AppBar → actions

 

Файл todo_screen.dart

import 'package:flutter/material.dart';  
  
import '../models/task.dart';  
  
class ToDoScreen extends StatefulWidget {  
  final bool isDarkMode;  
  final ValueChanged<bool> onThemeToggle; // Функция для переключения темы  
  
  const ToDoScreen({  
    super.key,  
    required this.isDarkMode,  
    required this.onThemeToggle,  
  });  
  
  @override  
  State<ToDoScreen> createState() => _ToDoScreenState();  
}  
  
class _ToDoScreenState extends State<ToDoScreen> {  
  // Контроллер для ввода текста  
  TextEditingController textEditingController = TextEditingController();  
  
  // Список задач  
  final List<Task> _tasks = [  
    Task(text: 'Купить молоко'),  
    Task(text: 'Изучить нейронки'),  
    Task(text: 'Купить RTX 5090', isDone: true), // Пример выполненной задачи  
  ];  
  
  // Метод для показа диалога добавления задачи  
  void showAddTaskDialog() {  
    showDialog(  
      context: context,  
      builder: (BuildContext context) {  
        return AlertDialog(  
          title: const Text('Добавить новую задачу'),  
          content: TextField(  
            controller: textEditingController,  
            decoration: const InputDecoration(hintText: "Введите текст задачи"),  
          ),  
          actions: <Widget>[  
            // Кнопка отмены  
            TextButton(  
              child: const Text('Отмена'),  
              onPressed: () {  
                Navigator.of(context).pop(); // Закрыть диалог  
              },  
            ),  
            // Кнопка добавления  
            TextButton(  
              child: const Text('Добавить'),  
              onPressed: () {  
                setState(() {  
                  // Добавляем задачу в список  
                  _tasks.add(Task(text: textEditingController.text));  
                  // Очищаем контроллер  
                  textEditingController.clear();  
                });  
                Navigator.of(context).pop(); // Закрыть диалог  
              },  
            ),  
          ],  
        );  
      },  
    );  
  }  
  
  @override  
  Widget build(BuildContext context) {  
    return Scaffold(  
      appBar: AppBar(  
        title: const Text('Список Задач'),  
        actions: [  
          Center(  
            child: Text(widget.isDarkMode ? 'Темная тема' : 'Светлая тема'),  
          ),  
          Switch(  
            // Значение Switch зависит от переданного состояния  
            value: widget.isDarkMode,  
            // При изменении вызываем переданную функцию  
            onChanged: widget.onThemeToggle,  
          ),  
          const SizedBox(width: 8), // Небольшой отступ справа  
        ],  
      ),  
  
      // Добавляем FAB  
      body: ListView.builder(  
        itemCount: _tasks.length, // Количество задач  
        itemBuilder: (context, index) {  
          final task = _tasks[index]; // Текущая задача  
  
          return ListTile(  
            // Чекбокс слева  
            leading: Checkbox(  
              value: task.isDone, // значение выполненности из объекта task  
              onChanged: (bool? newValue) {  
                // При изменении чекбокса, переключаем статус задачи  
                setState(() {  
                  task.isDone = newValue ?? false; // Меняем статус на новый  
                });  
              },  
            ),  
            // Текст задачи с зачеркиванием  
            title: Text(  
              task.text,  
              style: TextStyle(  
                decoration:  
                    task.isDone  
                        ? TextDecoration.lineThrough // Зачеркнутый, если выполнена  
                        : TextDecoration.none, // Обычный, если не выполнена  
              ),  
            ),  
          );  
        },  
      ),  
  
      floatingActionButton: FloatingActionButton.extended(  
        onPressed: showAddTaskDialog, // Вызываем метод показа диалога  
        label: const Text('Добавить'), // Текст на кнопке  
        icon: const Icon(Icons.add), // Иконка на кнопке  
        tooltip: 'Добавить новую задачу',  
      ),  
    );  
  }  
}


Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий